#pragma once

#include "zen_vap_sprite.h"
#include "zen_font.h"
#include "zen_class.h"
#include <vector>
#include <mutex>

namespace Zen { namespace Vap {

	class TextureWithRender {
	public:

		std::shared_ptr<FontRender> getFontRender() { return m_render; }

		void setFontRender(std::shared_ptr<FontRender> render);

		void setImageEffect(ImageEffectFunction effect);

		auto getImageEffect() { return m_image_effect; }

		void setUnderlineInPixels(int width);

		bool clearRenderDirty();

		SharedTexture getTextureRendered();

	private:

		std::shared_ptr<FontRender> m_render;

		ImageEffectFunction m_image_effect;

		std::shared_ptr<Image> m_image;

		int m_underline_px = 0;

		bool m_is_render_dirty = false;

		bool m_is_image_dirty = false;

		bool m_is_texture_empty = true;

		SharedTexture m_texture_rendered;
	};

	class TextureWithFont : public TextureWithRender
	{
	public:
		void setFontBrush(std::shared_ptr<FontBrush>);

		std::shared_ptr<FontBrush> getFontBrush() { return m_font; }
		// render config.
		void setTextAlignment(float alignment);

		void setMaxWidthInPixels(int pixels);

		void setCharsSpacingInPixels(int pixels);

		void setLinesSpacingInPixels(int pixels);

		float getTextAlignment() { return m_alignment; }

		int getMaxWidthInPixels() { return m_max_width_px; }

		int getCharsSpacingInPixels() { return m_char_spacing_px; }

		int getLinesSpacingInPixels() { return m_line_spacing_px; }

		void setText(std::string const & str);

		std::string const & getText() const { return m_text; }

		bool clearFontDirty();

	private:

		std::string m_text;
		std::u32string m_text32;
		std::shared_ptr<FontBrush> m_font;
		float m_alignment = 0;
		int m_max_width_px = 0;
		int m_char_spacing_px = 0;
		int m_line_spacing_px = 0;
		bool m_is_font_dirty = true;

		using TextureWithRender::setFontRender;
	};

	/*!
	 @class
	 @abstract a font label. <br>
	 the label use a font to render view, it's a slowly operation. <br>
	 so not good for dynamic text.
	 */
	class Label : public Sprite, public TextureWithFont {

	public:
		void setFontSize(float size);

		auto getFontSize() const { return m_font_size; }

		virtual void updateContent() override;

	protected:
		float m_font_size = 16;

		bool m_is_font_size_dirty = true;

		using TextureWithFont::clearFontDirty;
		using Sprite::setTexture;
		using Sprite::setTextureScale;
	};

}}
